package com.ming_za.sokoban.network;

import com.google.common.base.Suppliers;
import com.ming_za.sokoban.Sokoban;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;

import java.util.HashSet;
import java.util.function.Supplier;


public class NetworkUtils {
    public static final String version = "1";
    public static SimpleChannel sokobanChannel;

    /**
     * 存储在线玩家,用于发送群体或单个数据
     */
    private final HashSet<ServerPlayer> playerUUID = new HashSet<>();

    //供应商对象储存，只有第一次调用get()时会创建对象
    private static final Supplier<NetworkUtils> instance = Suppliers.memoize(NetworkUtils::new);

    public static NetworkUtils getInstance(){
        return instance.get();
    }

    public void initialize(){
        //网络
        sokobanChannel = NetworkRegistry.newSimpleChannel(new ResourceLocation(Sokoban.MOD_ID,"channel"),() -> version , version::equals, version::equals);

        sokobanChannel.registerMessage(0, UpdateClient.class,UpdateClient::encode,UpdateClient::decode,UpdateClient::handle);

        //监听在线玩家，存储玩家数据
        MinecraftForge.EVENT_BUS.addListener(this::playerLoggedIn);
        MinecraftForge.EVENT_BUS.addListener(this::playerLoggedOut);

    }

    private void playerLoggedIn(PlayerEvent.PlayerLoggedInEvent event){
        if (event.getEntity() instanceof ServerPlayer player){
            playerUUID.add(player);
        }
    }

    private void playerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event){
        if (event.getEntity() instanceof ServerPlayer player){
            playerUUID.remove(player);
        }
    }

    /**
     * 更新方块位置
     */
    public void s2c_clientUpdate(BlockPos pos, BlockPos rPos,Player player){
        for (ServerPlayer serverPlayer : playerUUID){
            if (!player.getStringUUID().equals(serverPlayer.getStringUUID())){
                sokobanChannel.sendTo(new UpdateClient(0,pos, rPos),serverPlayer.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
            }
        }
    }

    /**
     * 更新粒子效果
     */
    public void updateParticle(BlockPos pos,BlockPos rPos){
        for (ServerPlayer serverPlayer : playerUUID){
            assert Minecraft.getInstance().player != null;
            if (!Minecraft.getInstance().player.getStringUUID().equals(serverPlayer.getStringUUID())){
                sokobanChannel.sendTo(new UpdateClient(1,pos,rPos),serverPlayer.connection.connection, NetworkDirection.PLAY_TO_CLIENT);

            }
        }
    }

}
